package com.think.cloud.thinkshop.mall.service.memberuser.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.think.cloud.thinkshop.common.enums.RabbitMessageTypeEnum;
import com.think.cloud.thinkshop.common.enums.user.SwitchEnum;
import com.think.cloud.thinkshop.common.enums.user.UserRegistrationSource;
import com.think.cloud.thinkshop.mall.controller.admin.index.dto.StatisticalTrendViewDTO;
import com.think.cloud.thinkshop.mall.controller.admin.memberuser.dto.MemberGroupUserTraitDetailDTO;
import com.think.cloud.thinkshop.mall.controller.admin.memberuser.dto.MemberTagRefDTO;
import com.think.cloud.thinkshop.mall.controller.admin.memberuser.dto.MemberUserQueryDTO;
import com.think.cloud.thinkshop.mall.controller.admin.memberuser.dto.UpdateTagDTO;
import com.think.cloud.thinkshop.mall.controller.admin.memberuser.vo.MemberUserVO;
import com.think.cloud.thinkshop.mall.controller.app.memberuser.dto.ForgetPasswordDTO;
import com.think.cloud.thinkshop.mall.controller.app.memberuser.dto.RegisterDTO;
import com.think.cloud.thinkshop.mall.controller.app.memberuser.dto.UpdatePasswordDTO;
import com.think.cloud.thinkshop.mall.controller.app.memberuser.dto.UpdateUserInfoDTO;
import com.think.cloud.thinkshop.mall.convert.memberuser.MemberUserConvert;
import com.think.cloud.thinkshop.mall.domain.memberuser.MemberTagRef;
import com.think.cloud.thinkshop.mall.domain.memberuser.MemberUser;
import com.think.cloud.thinkshop.mall.mapper.memberuser.MemberUserMapper;
import com.think.cloud.thinkshop.mall.rabbit.producer.MessageProducer;
import com.think.cloud.thinkshop.mall.service.integral.IIntegralDetailService;
import com.think.cloud.thinkshop.mall.service.memberuser.IMemberTagRefService;
import com.think.cloud.thinkshop.mall.service.memberuser.IMemberUserService;
import com.think.cloud.thinkshop.mall.service.verificationcode.VerificationCodeService;
import com.think.cloud.thinkshop.mall.service.websitesetting.IWebsiteSettingService;
import com.think.cloud.thinkshop.system.api.dto.AuthUserDTO;
import com.think.cloud.thinkshop.system.api.dto.MemberUserDTO;
import com.think.common.core.exception.util.ServiceExceptionUtil;
import com.think.common.core.utils.PageUtils;
import com.think.common.core.utils.bean.BeanUtils;
import com.think.common.core.web.page.TableDataInfo;
import com.think.common.security.utils.SecurityUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.think.common.core.constant.VerificationCodeConstant.VERIFICATION_CODE_FORGET_KEY;
import static com.think.common.core.constant.VerificationCodeConstant.VERIFICATION_CODE_REGISTER_KEY;
import static com.think.common.core.exception.enums.ErrorCode.EMAIL_REGISTERED;
import static com.think.common.core.exception.enums.ErrorCode.USER_NOT_EXIST;
import static com.think.common.core.utils.PageUtils.startPage;

/**
 * 商城用户Service业务层处理
 *
 * @author zkthink
 * @date 2024-05-09
 */
@Service
@Slf4j
public class MemberUserServiceImpl implements IMemberUserService {
    @Autowired
    private MemberUserMapper memberUserMapper;
    @Autowired
    @Lazy
    private VerificationCodeService verificationCodeService;
    @Autowired
    private IWebsiteSettingService websiteSettingService;
    @Autowired
    private IMemberTagRefService memberTagRefService;
    @Autowired
    private MessageProducer messageProducer;
    @Autowired
    private IIntegralDetailService integralDetailService;

    /**
     * 查询商城用户
     *
     * @param id 商城用户主键
     * @return 商城用户
     */
    @Override
    public MemberUser selectMemberUserById(Long id) {
        return memberUserMapper.selectById(id);
    }

    @Override
    public MemberUserVO selectMemberUserVOById(Long id) {
        MemberUser memberUser = memberUserMapper.selectById(id);
        if (ObjectUtil.isNotNull(memberUser)) {
            MemberUserVO memberUserVO = MemberUserConvert.INSTANCE.convert(memberUser);
            fillData(Collections.singletonList(memberUserVO));
            return memberUserVO;
        }
        return null;
    }

    /**
     * 查询商城用户列表
     *
     * @param memberUser 商城用户
     * @return 商城用户
     */
    @Override
    public TableDataInfo selectMemberUserPage(MemberUserQueryDTO memberUser) {
        // 查询标签对应用户
        if(Objects.nonNull(memberUser.getTagIds())){
            List<MemberTagRef> memberTagRefs = memberTagRefService.selectByTagIds(memberUser.getTagIds());
            List<Long> userIds = memberTagRefs.stream().map(MemberTagRef::getUserId).distinct().collect(Collectors.toList());
            memberUser.setUserIds(userIds);
        }

        LambdaQueryWrapper<MemberUser> wrapper = buildQueryWrapper(memberUser);
        startPage();
        List<MemberUser> memberUsers = memberUserMapper.selectList(wrapper);
        List<MemberUserVO> memberUserVOS = MemberUserConvert.INSTANCE.convertList(memberUsers);
        //填充其他数据
        fillData(memberUserVOS);
        return new TableDataInfo(memberUserVOS, PageUtils.getTotal(memberUsers));
    }

    /**
     * 查询商城用户列表
     *
     * @param memberUser 商城用户
     * @return 商城用户
     */
    @Override
    public List<MemberUserVO> selectMemberUserList(MemberUserQueryDTO memberUser) {
        LambdaQueryWrapper<MemberUser> wrapper = buildQueryWrapper(memberUser);
        List<MemberUser> memberUsers = memberUserMapper.selectList(wrapper);
        return MemberUserConvert.INSTANCE.convertList(memberUsers);
    }

    private void fillData(List<MemberUserVO> memberUserVOS) {
        if (ObjectUtil.isNotEmpty(memberUserVOS)) {
            List<Long> userIds = memberUserVOS.stream().map(MemberUserVO::getId).collect(Collectors.toList());
            //查询用户标签
            List<MemberTagRefDTO> memberTagRefDTOS = memberTagRefService.selectByUserIds(userIds);
            Map<Long, List<MemberTagRefDTO>> tagMap = memberTagRefDTOS.stream().collect(Collectors.groupingBy(MemberTagRefDTO::getUserId));
            memberUserVOS.forEach(memberUserVO -> {
                Long id = memberUserVO.getId();
                memberUserVO.setTagList(tagMap.get(id));
                memberUserVO.setIntegral(integralDetailService.getUserCurrentIntegral(id));
            });
        }
    }

    /**
     * 新增商城用户
     *
     * @param memberUser 商城用户
     * @return 结果
     */
    @Override
    public int insertMemberUser(MemberUser memberUser) {

        return memberUserMapper.insert(memberUser);
    }

    /**
     * 修改商城用户
     *
     * @param memberUser 商城用户
     * @return 结果
     */
    @Override
    public int updateMemberUser(MemberUser memberUser) {
        return memberUserMapper.updateById(memberUser);
    }

    /**
     * 批量删除商城用户信息
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    public int batchDelete(List<Long> ids) {
        return memberUserMapper.deleteBatchIds(ids);
    }

    @Override
    public void register(RegisterDTO registerDTO) {
        //查询是否存在
        MemberUser memberUser = this.getByEmail(registerDTO.getEmail());
        if (Objects.nonNull(memberUser)) {
            throw ServiceExceptionUtil.exception(EMAIL_REGISTERED);
        }
        //校验验证码
        verificationCodeService.checkVerificationCode(VERIFICATION_CODE_REGISTER_KEY, registerDTO.getEmail(), registerDTO.getCode());
        //获取头像
        String avatar = getAvatar();
        MemberUser user = new MemberUser();
        user.setEmail(registerDTO.getEmail())
                .setUsername(registerDTO.getEmail())
                .setPassword(SecurityUtils.encryptPassword(registerDTO.getPassword()))
                .setFirstName(registerDTO.getFirstName())
                .setLastName(registerDTO.getLastName())
                .setSource(UserRegistrationSource.EMAIL.getCode())
                .setStatus(SwitchEnum.ACTIVE.getCode())
                .setAvatar(avatar);
        memberUserMapper.insert(user);

        //删除验证码
//        verificationCodeService.deleteVerificationCode(VERIFICATION_CODE_REGISTER_KEY, registerDTO.getEmail());
    }

    private String getAvatar() {
        String defaultAvatar = websiteSettingService.getCache().getDefaultAvatar();
        String avatar = "";
        if (Objects.nonNull(defaultAvatar)) {
            avatar = defaultAvatar;
        } else {
            log.warn("未配置默认头像");
        }
        return avatar;
    }

    @Override
    public MemberUser getByEmail(String email) {
        return memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getEmail, email));
    }

    @Override
    public MemberUserDTO getByUsername(String username) {
        MemberUser user = memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getUsername, username));
        MemberUserDTO memberUserDTO = new MemberUserDTO();
        BeanUtils.copyProperties(user, memberUserDTO);

        //触发自动客户分群
        messageProducer.sendMessage(String.valueOf(user.getId()), RabbitMessageTypeEnum.MEMBER_GROUP_UPDATE_BY_USER_ACTION);
        return memberUserDTO;
    }

    @Override
    public void forgetPassword(ForgetPasswordDTO forgetPassword) {
        MemberUser user = getByEmail(forgetPassword.getEmail());
        if (Objects.isNull(user)) {
            throw ServiceExceptionUtil.exception(USER_NOT_EXIST);
        }
        verificationCodeService.checkVerificationCode(VERIFICATION_CODE_FORGET_KEY, forgetPassword.getEmail(), forgetPassword.getCode());
        //修改密码
        user.setPassword(SecurityUtils.encryptPassword(forgetPassword.getPassword()));
        memberUserMapper.updateById(user);
        verificationCodeService.deleteVerificationCode(VERIFICATION_CODE_FORGET_KEY, forgetPassword.getEmail());
    }

    @Override
    public void updatePassword(Long userId, UpdatePasswordDTO updatePassword) {

    }

    @Override
    public MemberUserDTO oauthCallback(AuthUserDTO authUserDTO) {
        String source = authUserDTO.getSource();
        String uuid = authUserDTO.getUuid();
        //查询用户是否存在
        MemberUser user = getByThirdUid(source, uuid);
        if (Objects.isNull(user)) {
            user = new MemberUser();
            user.setSource(source)
                    .setThirdUid(uuid)
                    .setSource(source)
                    .setUsername(authUserDTO.getEmail())
                    .setEmail(authUserDTO.getEmail())
                    .setAvatar(authUserDTO.getAvatar())
                    .setLastName(authUserDTO.getNickname());
            memberUserMapper.insert(user);
        }
        MemberUserDTO memberUserDTO = new MemberUserDTO();
        BeanUtils.copyProperties(user, memberUserDTO);
        return memberUserDTO;
    }

    @Override
    public void updateTag(UpdateTagDTO updateTagDTO) {
        Long userId = updateTagDTO.getId();
        //删除用户标签
        memberTagRefService.deleteByUserId(userId);
        //插入标签
        List<Long> tagIds = updateTagDTO.getTagIds();
        List<MemberTagRef> list = tagIds.stream().map(tagId -> new MemberTagRef(userId, tagId)).collect(Collectors.toList());
        Db.saveBatch(list, list.size());
        //触发自动客户分群
        messageProducer.sendMessage(String.valueOf(userId), RabbitMessageTypeEnum.MEMBER_GROUP_UPDATE_BY_USER_ACTION);
    }

    @Override
    public void updateUserInfo(Long userId, UpdateUserInfoDTO infoDTO) {
        MemberUser memberUser = new MemberUser();
        memberUser.setId(userId)
                .setFirstName(infoDTO.getFirstName())
                .setLastName(infoDTO.getLastName())
        ;
        memberUserMapper.updateById(memberUser);
    }

    private MemberUser getByThirdUid(String source, String uuid) {
        return memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getThirdUid, uuid).eq(MemberUser::getSource, source));
    }

    public LambdaQueryWrapper<MemberUser> buildQueryWrapper(MemberUserQueryDTO queryDTO) {
        LambdaQueryWrapper<MemberUser> wrapper = new LambdaQueryWrapper<>();

        if (queryDTO.getStartLastConsumeTime() != null) {
            wrapper.ge(MemberUser::getLastConsumeTime, queryDTO.getStartLastConsumeTime());
        }
        if (queryDTO.getEndLastConsumeTime() != null) {
            wrapper.le(MemberUser::getLastConsumeTime, queryDTO.getEndLastConsumeTime());
        }
        if (queryDTO.getStartCreateTime() != null) {
            wrapper.ge(MemberUser::getCreateTime, queryDTO.getStartCreateTime());
        }
        if (queryDTO.getEndCreateTime() != null) {
            wrapper.le(MemberUser::getCreateTime, queryDTO.getEndCreateTime());
        }
        if (!StringUtils.isBlank(queryDTO.getEmail())) {
            wrapper.eq(MemberUser::getEmail, queryDTO.getEmail());
        }
        if (queryDTO.getUserIds() != null && !queryDTO.getUserIds().isEmpty()) {
            wrapper.in(MemberUser::getId, queryDTO.getUserIds());
        }
        wrapper.orderByDesc(MemberUser::getId);
        return wrapper;
    }

    /**
     * 用户注册趋势
     *
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public List<StatisticalTrendViewDTO> memberRegisterTrend(String startTime, String endTime) {
        return memberUserMapper.registeredUserCount(startTime, endTime);
    }

    /**
     * 用户总数
     *
     * @return
     */
    @Override
    public Long memberUserCount() {
        return memberUserMapper.selectCount(Wrappers.lambdaQuery());
    }

    /**
     * 范围内注册的用户数量
     *
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public Long memberUserCount(String startTime, String endTime) {
        return memberUserMapper.selectCount(statisticCondition(startTime, endTime));
    }

    @Override
    public List<StatisticalTrendViewDTO> newMemberCountTrend(String startTime, String endTime) {
        return memberUserMapper.newMemberCountTrend(statisticCondition(startTime, endTime));
    }

    /**
     * 统计的查询条件
     */
    private LambdaQueryWrapper<MemberUser> statisticCondition(String startTime, String endTime) {
        return Wrappers.<MemberUser>lambdaQuery()
                .ge(ObjectUtil.isNotNull(startTime), MemberUser::getCreateTime, startTime)
                .le(ObjectUtil.isNotNull(startTime), MemberUser::getCreateTime, endTime)
                ;
    }

    @Override
    public List<MemberGroupUserTraitDetailDTO> memberAllUserTrait() {
        List<MemberGroupUserTraitDetailDTO> detailDTOS = memberUserMapper.memberUserTrait(null);
        return memberAllUserTagsTrait(detailDTOS);
    }

    @Override
    public List<MemberGroupUserTraitDetailDTO> memberGroupUserTrait(Long userId) {
        List<MemberGroupUserTraitDetailDTO> detailDTOS = memberUserMapper.memberUserTrait(userId);
        if (detailDTOS.isEmpty() ||(detailDTOS.size() == 1 && detailDTOS.get(0) == null)) {
            detailDTOS = new ArrayList<>();
            MemberGroupUserTraitDetailDTO item = new MemberGroupUserTraitDetailDTO();
            item.setUserId(userId);
            detailDTOS.add(item);
        }
        detailDTOS = detailDTOS.stream().peek(memberGroupUserTraitDetailDTO -> {
            if (memberGroupUserTraitDetailDTO == null) {
                memberGroupUserTraitDetailDTO = new MemberGroupUserTraitDetailDTO();
            }
            memberGroupUserTraitDetailDTO.setUserId(userId);
        }).collect(Collectors.toList());
        return memberAllUserTagsTrait(detailDTOS);
    }

    @Override
    public void updateConsume(Long id, BigDecimal payPrice) {
        memberUserMapper.updateConsume(id, payPrice);
    }

    @Override
    public void updateUserRefundData(Long userId, BigDecimal refundAmount) {
        memberUserMapper.updateUserRefundData(userId, refundAmount);
    }

    /**
     * 填充用户的特征中的标签
     *
     * @param detailDTOS
     * @return
     */
    private List<MemberGroupUserTraitDetailDTO> memberAllUserTagsTrait(List<MemberGroupUserTraitDetailDTO> detailDTOS) {
        List<MemberGroupUserTraitDetailDTO> resultSet = detailDTOS.stream().peek(vo -> {
            List<MemberTagRefDTO> memberTagRefDTOS = memberTagRefService.selectByUserIds(Collections.singletonList(vo.getUserId()));
            if (memberTagRefDTOS != null && !memberTagRefDTOS.isEmpty()) {
                List<Long> tagIds = memberTagRefDTOS.stream().map(MemberTagRefDTO::getTagId).collect(Collectors.toList());
                vo.setTags(tagIds);
            }
        }).collect(Collectors.toList());
        log.info(" | 当前用户特征：=================>");
        detailDTOS.forEach(item -> log.info("=> {}", JSONObject.toJSONString(item, JSONWriter.Feature.WriteNulls)));
        return resultSet;
    }

    private static final String TARGET_PACKAGE = "com.think.cloud.thinkshop.mall.controller.app";
    @Async
    @SneakyThrows
    @Override
    public void recordUserOpt(String uri, Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取Controller类的Class对象
            Class<?> beanType = handlerMethod.getBeanType();
            // 检查这个类是否在你指定的包或其子包中
            if (beanType.getName().startsWith(TARGET_PACKAGE)) {
                Long userId = SecurityUtils.getUserId();
                if (!userId.equals(0L)) {
                    // todo sync or mq
                    System.err.println(userId + " ------- " + uri);
                }
            }
        }
    }
}
